#include <stdio.h>
#include <stdlib.h>

#include "TestSuite.h"

TestSuite* TestSuiteCreate()
{
	//Allocate the memory for the structure.
	TestSuite* pTestSuite = (TestSuite*)calloc(sizeof(TestSuite), 1);

	//Return the structure.
	return pTestSuite;
}

void TestSuiteDelete(TestSuite* pTestSuite)
{
	//Delete all unit tests first.
	pTestSuite->current = pTestSuite->first;
	while (pTestSuite->first != 0)
	{
		pTestSuite->first = pTestSuite->current->next;
		UnitTestDelete(pTestSuite->current);
	}

	//Finally free the test suite structure.
	free(pTestSuite);
}

void UnitTestDelete(UnitTest* pUnitTest)
{
	//Delete the name of the test.
	free(pUnitTest->name);

	//Delete the test structure.
	free(pUnitTest);
}

UnitTest* UnitTestCreate(char* sName, TestMethod fTestMethod)
{
	int length = 255;
	char* sTemporaryName;
	UnitTest* pUnitTest;

	//Allocate memory to the test structure and add the test method to it.
	pUnitTest = (UnitTest*)calloc(sizeof(UnitTest), 1);
	pUnitTest->method = fTestMethod;

	//Copy the name characters into the structure name variable.
	sTemporaryName = pUnitTest->name;
	while ((*sName != 0) && (length-- >= 0)) *((char*)sTemporaryName++) = *((char*)sName++);
	*sTemporaryName = 0;

	//Return the test method.
	return pUnitTest;
}

void TestSuiteAdd(TestSuite* pTestSuite, char* sName, TestMethod fTestMethod)
{
	//Create a test structure and add the test to the test suite.
	UnitTest* pUnitTest = UnitTestCreate(sName, fTestMethod);

	//If there are no methods added yet, add it in the top.
	if (pTestSuite->first == 0)
	{
		pTestSuite->first = pUnitTest;
		pTestSuite->last = pUnitTest;
	}
	//Otherwise add it to the end of the linked list.
	else
	{
		pTestSuite->last->next = pUnitTest;
		pTestSuite->last = pUnitTest;
	}
}

void TestSuiteRun(TestSuite* pTestSuite)
{
	//Clear the test suite totals.
	pTestSuite->total = 0;
	pTestSuite->failed = 0;

	//Start for the first test.
	pTestSuite->current = pTestSuite->first;
	while (pTestSuite->current != 0)
	{
		printf("\n\nTEST: %s", pTestSuite->current->name);

		//Create the current method totals.
		pTestSuite->current->total = 0;
		pTestSuite->current->failed = 0;

		//Call the method passing the test suite structure.
		pTestSuite->current->method(pTestSuite);

		//If There where any failures within the current test then increment the global failure number by one.
		if (pTestSuite->current->failed > 0) pTestSuite->failed++;

		//More to the next test.
		pTestSuite->current = pTestSuite->current->next;
	}

	//Finally report the total number of test methods and the total number of failures.
	printf("\n\nTOTAL : %i", pTestSuite->total);
	printf("\nFAILED: %i\n", pTestSuite->failed);
}

int Assert(TestSuite* pTestSuite, int iResult, char* sMessage)
{
	//Increments the total asserts for the current method by one.
	pTestSuite->current->total++;

	//If assert failed
	if (!iResult)
	{
		//Increment the total number of failures within the current test.
		pTestSuite->current->failed++;

		//Report to user.
		printf("\n*\tFAILED : %s", sMessage);
	}
	//Otherwise report success to user.
	else printf("\n\tSUCCESS");

	return (iResult != 0);
}

